package yixaun.tim.service.impl;

import com.tencentyun.TLSSigAPIv2;
import lombok.Data;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import yixaun.tim.common.BaseVo;
import yixaun.tim.common.TimException;
import yixaun.tim.config.TimProperties;
import yixaun.tim.service.*;
import yixaun.tim.util.JsonUtils;
import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.Map;

/**
 * @author pengshiqing
 * @Date: 2019/6/22
 * @Description:
 */
@Data
@Slf4j
public class TimServiceImpl implements TimService {

    private TimProperties timProperties ;
    private TimAccountService timAccountService ;
    private TimOnlineStatusService timOnlineStatusService ;
    private TimRelationService timRelationService ;
    private TimChatService timChatService ;
    private TimProfileService profileService ;
    private TimGroupService timGroupService ;

    private final OkHttpClient HTTP_CLIENT = new OkHttpClient();
    private final MediaType JSON = MediaType.get("application/json; charset=utf-8");


    public TimServiceImpl(TimProperties timProperties) {
        this.timProperties = timProperties;
        this.timAccountService = new TimAccountServiceImpl(this);
        this.timOnlineStatusService = new TimOnlineStatusServiceImpl(this);
        this.timRelationService = new TimRelationServiceImpl(this);
        this.timChatService = new TimChatServiceImpl(this);
        this.profileService = new TimProfileServiceImpl(this);
        this.timGroupService = new TimGroupServiceImpl(this);
    }


    /** 获取配置 */
    @Override
    public TimProperties getTimProperties() {
        return timProperties;
    }

    @Override
    public TimAccountService getTIMAccountService() {
        return timAccountService;
    }

    @Override
    public TimOnlineStatusService getTIMOnlineStatusService() {
        return timOnlineStatusService ;
    }

    @Override
    public TimRelationService getTIMRelationService() {
        return timRelationService ;
    }

    @Override
    public TimChatService getTIMChatService() {
        return timChatService;
    }

    @Override
    public TimGroupService getTimGroupService() {
        return timGroupService;
    }

    @Override
    public TimProfileService getTIMProfileService() {
        return profileService;
    }


    /**
     * 获取UserSig信息
     * @param identifier 用户id
     */
    @Override
    public String getUserSig(@NonNull String identifier) throws TimException {
        // 默认时间 30 天
        int time = 60 * 60 * 24 * 30;
        return getUserSig(identifier,time);
    }

    /**
     * 获取UserSig信息
     * @param identifier 用户id
     * @param time     超时时间 秒
     */
    @Override
    public String getUserSig(@NonNull String identifier, Integer time) throws TimException {
        // TLSSigAPIv2 api = new TLSSigAPIv2(1400395288, "0aec34dd4d4a3761c3a97824fca21611443976beb4e9e4fa5a7babf73389437a");
        TLSSigAPIv2 api = new TLSSigAPIv2(timProperties.getAppId(), timProperties.getPrivateKey());
        return api.genSig(identifier, time) ;
    }






    /***************************************/
    /************* 通用方法 *****************/
    /***************************************/

    /** 通用GET方法 */
    @Override
    public String get(String api, Map<String, String> queryParams) throws TimException {

        String url = buildFullUrl(api, queryParams);

        log.debug("【TIMJava】 request method : {}, url：{}", "GET", url);

        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        return execute(request);
    }

    /** 通用POST方法 */
    @Override
    public String post(String api, Object body) throws TimException {

        String url = buildFullUrl(api, null);
        String json = JsonUtils.toJson(body);

        log.debug("【TIMJava】 request method : {}, url：{}", "POST",url);
        log.debug("【TIMJava】 request body : {} ",json);

        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(JSON, json))
                .build();

        return execute(request);
    }

    private String buildFullUrl(String api, Map<String, String> queryParams) throws TimException {
        Long appid = this.getTimProperties().getAppId();
        String adminIdentifier = this.getTimProperties().getAdminIdentifier();
        String userSig = this.getUserSig(adminIdentifier);
        String randomText = (Math.random() * 10000000 + "").substring(0, 8);
        String contentType = "json";
        String server = "https://console.tim.qq.com";
        String urlTemplate = server + "/" + api + "?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=%s";
        String url = String.format(urlTemplate, appid, adminIdentifier, userSig, randomText, contentType);
        if (queryParams != null) {
            Iterator<Map.Entry<String, String>> iterator = queryParams.entrySet().iterator();
            Map.Entry<String, String> entry;
            while (iterator.hasNext()) {
                entry = iterator.next();
                url += "&" + entry.getKey() + "=" + entry.getValue();
            }
        }
        return url;
    }


    private String execute(Request request) throws TimException {
        return execute(request, 1);
    }

    private String execute(Request request, int reqCount) throws TimException {
        try {
            log.debug("【TIMJava】 发起请求 当前第 {} 次 / {} 次 {}", reqCount, timProperties.getReqReTryCount(), reqCount > 1 ? "[重试请求]" : "");
            return executeInternal(request);
        } catch (SocketTimeoutException e) {
            if (reqCount >= timProperties.getReqReTryCount()) {
                throw new TimException(0, "请求失效,请检查你的网络状态");
            }
            // 执行重试
            return execute(request, reqCount++);
        } catch (TimException e) {
            e.printStackTrace();
            throw new TimException(e.getErrorCode(), e.getErrorInfo());
        }catch (Exception e) {
            e.printStackTrace();
            throw new TimException(0, e.getMessage());
        }
    }

    private String executeInternal(Request request) throws Exception {
        Response response = HTTP_CLIENT.newCall(request).execute();
        String jsonResult = response.body().string();
        BaseVo baseVo = JsonUtils.fromJson(jsonResult, BaseVo.class);
        if ( baseVo.getErrorCode() != 0) {
            throw new TimException(baseVo.getErrorCode(),baseVo.getErrorInfo());
        }
        log.debug("【TIMJava】response body -------- ");
        log.debug(jsonResult);
        log.debug("【TIMJava】response body -------- ");
        return jsonResult;
    }


}
